package com.wxxymaker.service.impl;

import com.wxxymaker.model.dao.DeletedShopDao;
import com.wxxymaker.model.dao.ShopDao;
import com.wxxymaker.model.entity.DeletedShop;
import com.wxxymaker.model.entity.DeletedStageCount;
import com.wxxymaker.model.entity.Shop;
import com.wxxymaker.model.entity.StageCount;
import com.wxxymaker.service.ShopService;
import com.wxxymaker.service.StageCountService;
import com.wxxymaker.utils.Const;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: Soft
 * @Date: 2018/5/5 21:03
 * @Desc: 被打分公司业务层
 */
@Service
public class ShopServiceImpl implements ShopService {

    @Autowired
    private ShopDao dao;

    @Autowired
    private DeletedShopDao deletedShopDao;

    @Override
    @Transactional
    public Shop add(Shop shop) {
        return dao.save(shop);
    }

    @Override
    @Transactional
    public Shop delete(Integer id) {
        Shop shop = dao.findOne(id);
        if (null != shop) {
            dao.delete(shop);
            DeletedShop deletedShop = DeletedShop.copy(shop);
            List<DeletedStageCount> deletedStageCounts = shop.getStageCounts()
                    .stream()
                    .map(count -> {
                        DeletedStageCount copy = DeletedStageCount.copy(count);
                        copy.setShop(deletedShop);
                        return copy;
                    })
                    .collect(Collectors.toList());
            deletedShop.setStageCounts(deletedStageCounts);
            deletedShopDao.save(deletedShop);
        }
        return shop;
    }

    @Override
    @Transactional
    public boolean change(Shop shop) {
        Integer id = shop.getId();
        if (null != id && id > 0) {
            Shop one = (Shop) dao.findOne(id).extend(shop);
            return null != dao.saveAndFlush(one);
        }
        return false;
    }

    @Override
    public Shop getOne(Integer id) {
        return dao.findOne(id);
    }

    @Override
    public Shop getByName(String name) {
        return dao.findByNameLike(name);
    }

    @Override
    public Page<Shop> page(Integer pageNo, Integer size, Integer[] ids, Integer... types) {
        Specification<Shop> specification = new Specification<Shop>() {
            @Override
            public Predicate toPredicate(Root<Shop> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> ps = new LinkedList<>();
                if (ids != null && ids.length > 0) {
                    ps.add(root.get("id").in(ids));
                }
                if (types != null && types.length > 0) {
                    ps.add(root.get("type").in(types));
                }
                query.where(ps.toArray(new Predicate[ps.size()]));
                return null;
            }
        };
        if (pageNo < 1) {
            pageNo = 1;
        }
        Pageable pageable = new PageRequest(pageNo - 1, size,
                new Sort(Sort.Direction.DESC, "total"));
        return dao.findAll(specification, pageable);
    }

    @Override
    public Page<Shop> page(Integer pageNo, Integer size, Integer... types) {
        return this.page(pageNo, size, null, types);
    }

    @Override
    public Page<Shop> page(Integer pageNo) {
        return this.page(pageNo, Const.pageSize, null);
    }

    @Override
    public Shop getBest(Integer... type) {
        Specification<Shop> specification = (root, query, cb) -> {
            if (type != null && type.length > 0) {
                query.where(root.get("type").in(type));
            }
            return null;
        };
        Pageable pageable = new PageRequest(0, 1, new Sort(Sort.Direction.DESC, "total"));
        Page<Shop> all = dao.findAll(specification, pageable);
        if (all.getContent().size() > 0) {
            return all.getContent().get(0);
        }
        return null;
    }

    @Override
    public List<Shop> findAll() {
        return this.findAll(new Sort(Sort.Direction.DESC, "total"));
    }

    @Override
    public List<Shop> findAll(Sort sort) {
        return dao.findAll(sort);
    }

    @Override
    public List<Shop> findByIds(Integer... ids) {
        return dao.findByIdIn(ids);
    }

    @Override
    public List<Shop> findByType(Integer... types) {
        return dao.findByTypeIn(types);
    }

    @Override
    public List<Shop> findByNoType(Integer... types) {
        return dao.findByTypeNotIn(types);
    }

    @Override
    public void setTotalAndPrev(Shop shop, double nowTotal, double stageTotal) {
        shop.setPrevTotal(nowTotal);
        shop.setTotal(stageTotal);
        dao.saveAndFlush(shop);
    }
}
